home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / JFC.bin / TableView.java < prev    next >
Text File  |  1998-06-30  |  11KB  |  399 lines

  1. /*
  2.  * @(#)TableView.java    1.7 98/04/09
  3.  * 
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  */
  20. package com.sun.java.swing.text;
  21.  
  22. import java.awt.*;
  23.  
  24. /**
  25.  * <p>
  26.  * Implements View interface for a table, that is composed of a
  27.  * specific element structure where the child elements of the element
  28.  * this view is responsible for represent rows and the child 
  29.  * elements of the row elements are cells.  The cell elements can
  30.  * have an arbitrary element structure under them.
  31.  * <pre><code>
  32.  *   TABLE
  33.  *     ROW
  34.  *       CELL
  35.  *       CELL
  36.  *     ROW
  37.  *       CELL
  38.  *       CELL
  39.  * </code></pre>
  40.  * <p>
  41.  * This is implemented as a hierarchy of boxes, the table itself
  42.  * is a vertical box, the rows are horizontal boxes, and the cells
  43.  * are vertical boxes.  The cells are allowed to span multiple
  44.  * columns and rows.  By default, the table can be thought of as
  45.  * being formed over a grid, where cells can request to span more
  46.  * than one grid cell.  The default horizontal span of table cells
  47.  * will be based upon this grid, but can be changed by reimplementing
  48.  * the requested span of the cell.
  49.  * 
  50.  * @author  Timothy Prinzing
  51.  * @version 1.7 04/09/98
  52.  * @see     View
  53.  */
  54. public class TableView extends BoxView {
  55.  
  56.     /**
  57.      * Constructs a TableView for the given element.
  58.      *
  59.      * @param elem the element that this view is responsible for
  60.      */
  61.     public TableView(Element elem) {
  62.     super(elem, View.Y_AXIS);
  63.     }
  64.  
  65.     /**
  66.      * Creates a new table row.
  67.      *
  68.      * @param elem an element
  69.      * @return the row
  70.      */
  71.     protected TableRow createTableRow(Element elem) {
  72.     return new TableRow(elem);
  73.     }
  74.  
  75.     /**
  76.      * Creates a new table cell.
  77.      *
  78.      * @param elem an element
  79.      * @return the cell
  80.      */
  81.     protected TableCell createTableCell(Element elem) {
  82.     return new TableCell(elem);
  83.     }
  84.     
  85.     /**
  86.      * Fetches the span (width) of the given column.  
  87.      * This is used by the nested cells to query the 
  88.      * sizes of grid locations outside of themselves.
  89.      */
  90.     int getColumnSpan(int col) {
  91.     return colWidths[col];
  92.     }
  93.  
  94.     /**
  95.      * Fetches the span (height) of the given row.
  96.      * This is used by the nested cells to query the 
  97.      * sizes of grid locations outside of themselves.
  98.      */
  99.     int getRowSpan(int row) {
  100.     View v = getView(row);
  101.     return (int) v.getPreferredSpan(Y_AXIS);
  102.     }
  103.  
  104.     /**
  105.      * Loads all of the children to initialize the view.
  106.      * This is called by the <code>setParent</code> method.
  107.      * This is reimplemented to build rows using the
  108.      * <code>createTableRow</code> method and then 
  109.      * proxy cell entries for each of the cells that
  110.      * span multiple columns or rows, substantially 
  111.      * reducing the complexity of the layout calculations.
  112.      *
  113.      * @param f the view factory
  114.      */
  115.     protected void loadChildren(ViewFactory f) {
  116.     Element e = getElement();
  117.     int n = e.getElementCount();
  118.     if (n > 0) {
  119.         View[] added = new View[n];
  120.         for (int i = 0; i < n; i++) {
  121.         added[i] = createTableRow(e.getElement(i));
  122.         }
  123.         replace(0, 0, added);
  124.     }
  125.  
  126.     // fill in the proxy cells
  127.     for (int row = 0; row < n; row++) {
  128.         View rv = getView(row);
  129.         for (int col = 0; col < rv.getViewCount(); col++) {
  130.         View cv = rv.getView(col);
  131.         if (cv instanceof TableCell) {
  132.             TableCell cell = (TableCell) cv;
  133.             if ((cell.getColumnCount() > 1) ||
  134.             (cell.getRowCount() > 1)) {
  135.             
  136.             // fill in the proxy entries for this cell
  137.             for (int i = row; i < row + cell.getRowCount(); row++) {
  138.                 for (int j = col; j < col + cell.getColumnCount(); j++) {
  139.                 if (i != 0 && j != 0) {
  140.                     addProxy(i, j, cell);
  141.                 }
  142.                 }
  143.             }
  144.             }
  145.         }
  146.         }
  147.     }
  148.  
  149.     calculateGrid();
  150.     }
  151.  
  152.     void calculateGrid() {
  153.     int ncols = 0;
  154.     int nrows = getViewCount();
  155.     for (int i = 0; i < nrows; i++) {
  156.         View row = getView(i);
  157.         ncols = Math.max(ncols, row.getViewCount());
  158.     }
  159.  
  160.     colWidths = new int[ncols];
  161.     for (int i = 0; i < nrows; i++) {
  162.         View row = getView(i);
  163.         ncols = row.getViewCount();
  164.         for (int j = 0; j < ncols; j++) {
  165.         TableCell cell = (TableCell) row.getView(j);
  166.         colWidths[j] = Math.max(cell.getPreferredColumnSpan(), 
  167.                     colWidths[j]);
  168.         }
  169.         row.preferenceChanged(null, true, false);
  170.     }
  171.  
  172.     }
  173.  
  174.     /**
  175.      * Adds a cell to fill in for another cells overflow.  The proxy cells
  176.      * are simply for simplification of layout and have no useful semantics.
  177.      */
  178.     void addProxy(int row, int col, TableCell host) {
  179.     TableRow rv = (TableRow) getView(row);
  180.     rv.insert(col, new ProxyCell(host));
  181.     }
  182.  
  183.     /**
  184.      * Performs layout of the children.  The size is the
  185.      * area inside of the insets.  The table layout is mostly
  186.      * the default behavior of the boxes, where the requests
  187.      * made by the cells for their width is based upon 
  188.      * a common set of values held in the table.  The table
  189.      * itself calculates these values before the layout 
  190.      * proceeds and these values get used by the cells.
  191.      *
  192.      * @param width the width >= 0
  193.      * @param height the height >= 0
  194.      */
  195.     protected void layout(int width, int height) {
  196.     calculateGrid();
  197.     super.layout(width, height);
  198.     }
  199.  
  200.     // ---- View methods ----------------------------------------------------
  201.  
  202.     int[] colWidths;
  203.  
  204.     /**
  205.      * View of a row in a table.
  206.      */
  207.     public class TableRow extends BoxView {
  208.  
  209.     /**
  210.      * Constructs a TableView for the given element.
  211.      *
  212.      * @param elem the element that this view is responsible for
  213.      */
  214.         public TableRow(Element elem) {
  215.         super(elem, View.X_AXIS);
  216.     }
  217.  
  218.     /**
  219.      * Loads all of the children to initialize the view.
  220.      * This is called by the <code>setParent</code> method.
  221.      * This is reimplemented to build cells using the
  222.      * <code>createTableCell</code> method.
  223.      *
  224.      * @param f the view factory
  225.      */
  226.         protected void loadChildren(ViewFactory f) {
  227.         Element e = getElement();
  228.         int n = e.getElementCount();
  229.         if (n > 0) {
  230.         View[] added = new View[n];
  231.         for (int i = 0; i < n; i++) {
  232.             added[i] = createTableCell(e.getElement(i));
  233.         }
  234.         replace(0, 0, added);
  235.         }
  236.     }
  237.     
  238.     }
  239.  
  240.     /**
  241.      * View of a cell in a table
  242.      */
  243.     public class TableCell extends BoxView {
  244.  
  245.     /**
  246.      * Constructs a TableCell for the given element.
  247.      *
  248.      * @param elem the element that this view is responsible for
  249.      */
  250.         public TableCell(Element elem) {
  251.         super(elem, View.Y_AXIS);
  252.     }
  253.     
  254.     /**
  255.      * Gets the number of columns this cell spans (e.g. the
  256.      * grid width).
  257.          *
  258.          * @return the number of columns
  259.      */
  260.     public int getColumnCount() {
  261.         return 1;
  262.     }
  263.  
  264.     /**
  265.      * Gets the number of rows this cell spans (that is, the
  266.      * grid height).
  267.          *
  268.          * @return the number of rows
  269.      */
  270.     public int getRowCount() {
  271.         return 1;
  272.     }
  273.  
  274.         /**
  275.          * Sets the grid location.
  276.          *
  277.          * @param row the row >= 0
  278.          * @param col the column >= 0
  279.          */
  280.         public void setGridLocation(int row, int col) {
  281.             this.row = row;
  282.             this.col = col;
  283.     }
  284.  
  285.         /**
  286.      * Gets the preferred span for the column occupied.  This
  287.      * is basically the host's desired column span.
  288.      * The host divides its desired across the number
  289.      * of grid points.
  290.          *
  291.          * @return the span
  292.          */
  293.         public int getPreferredColumnSpan() {
  294.         return ((int) super.getPreferredSpan(X_AXIS)) / getColumnCount();
  295.     }
  296.  
  297.     // --- View methods -----------------------------
  298.  
  299.     /**
  300.      * Renders using the given rendering surface and area on that
  301.      * surface.  This is implemented to delegate to the superclass 
  302.      * after adjusting the allocation if needed because the 
  303.      * cell spans multiple grid points (eg. muliple columns
  304.      * and/or rows).
  305.      *
  306.      * @param g the rendering surface to use
  307.      * @param allocation the allocated region to render into
  308.      * @see View#paint
  309.      */
  310.         public void paint(Graphics g, Shape allocation) {
  311.         Rectangle alloc = allocation.getBounds();
  312.         int nrows = getRowCount();
  313.         int ncols = getColumnCount();
  314.         if (nrows > 1 || ncols > 1) {
  315.         // adjust the allocation
  316.         for (int i = 1; i < ncols; i++) {
  317.             alloc.width += getColumnSpan(col + i);
  318.         }
  319.         for (int i = 1; i < nrows; i++) {
  320.             alloc.height += getRowSpan(row + i);
  321.         }
  322.         }
  323.     }
  324.  
  325.     /**
  326.      * Determines the preferred span for this view along an
  327.      * axis.  For the x axis, this is implemented to return
  328.      * the column width for the grid location that this cell
  329.      * lives at.  This is the method that is effectively 
  330.      * controlling the layout of the table.  Cells can be
  331.      * independantly altered by re-implementing this method.
  332.      *
  333.      * @param axis may be either View.X_AXIS or View.Y_AXIS
  334.      * @returns  the span the view would like to be rendered into.
  335.      *           Typically the view is told to render into the span
  336.      *           that is returned, although there is no guarantee.  
  337.      *           The parent may choose to resize or break the view.
  338.      */
  339.         public float getPreferredSpan(int axis) {
  340.         switch (axis) {
  341.         case View.X_AXIS:
  342.         return getColumnSpan(col);
  343.         default:
  344.         return super.getPreferredSpan(axis);
  345.         }
  346.     }
  347.  
  348.     int row;
  349.     int col;
  350.     }
  351.  
  352.     /**
  353.      * A special table cell that simply occupies space in the
  354.      * table at a grid location to make calculations easier to
  355.      * deal with.
  356.      */
  357.     class ProxyCell extends TableCell {
  358.  
  359.     ProxyCell(TableCell host) {
  360.         super(host.getElement());
  361.     }
  362.     
  363.     /**
  364.      * Loads all of the children to initialize the view.
  365.      * This is called by the <code>setParent</code> method.
  366.      * This is reimplemented to do nothing... proxy cells 
  367.      * are just a place holder.
  368.      *
  369.      * @param f the view factory
  370.      */
  371.         protected void loadChildren(ViewFactory f) {
  372.     }
  373.  
  374.     /**
  375.      * Gets the preferred span for the column occupied.  This
  376.      * is basically the host's desired column span.
  377.      * The host divides its desired across the number
  378.      * of grid points.
  379.      */
  380.         public int getPreferredColumnSpan() {
  381.         return host.getPreferredColumnSpan();
  382.     }
  383.  
  384.     /**
  385.      * Renders using the given rendering surface and area on that
  386.      * surface.  This is implemented to do nothing as proxy cells
  387.      * are supposed to be invisible place holders.
  388.      *
  389.      * @param g the rendering surface to use
  390.      * @param allocation the allocated region to render into
  391.      * @see View#paint
  392.      */
  393.         public void paint(Graphics g, Shape allocation) {
  394.     }
  395.  
  396.     TableCell host;
  397.     }
  398. }
  399.